﻿using System.IO.Ports;
using UtilZ.Dotnet.Ex.Communication.Base;

namespace UtilZ.Dotnet.Ex.Communication.Ports
{
    /// <summary>
    /// 串口类
    /// </summary>
    public class SerialPortEx : SerialPortAbs
    {
        private readonly SerialPort _serialPort = null;

        /// <summary>
        /// 构造函数
        /// </summary>
        public SerialPortEx(IClientInitPara initPara)
            : base()
        {
            var serialPortInfo = (SerialPortClientInitPara)initPara;
            var serialPort = new SerialPort(serialPortInfo.PortName, serialPortInfo.BaudRate, (Parity)(int)serialPortInfo.Parity, serialPortInfo.DataBits, (StopBits)(int)serialPortInfo.StopBits);
            serialPort.DataReceived += this.SerialPort_DataReceived;
            serialPort.ErrorReceived += this.SerialPort_ErrorReceived;
            serialPort.PinChanged += this.SerialPort_PinChanged;
            serialPort.ReadBufferSize = serialPortInfo.ReceiveBufferSize;
            serialPort.WriteBufferSize = serialPortInfo.SendBufferSize;
            this._serialPort = serialPort;
        }

        private void SerialPort_PinChanged(object sender, SerialPinChangedEventArgs e)
        {
            base.OnRaisePinChanged((SerialPortPinChange)((int)e.EventType));
        }

        private void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
        {
            base.OnRaiseErrorReceived((SerialPortError)((int)e.EventType));
        }

        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            base.OnRaiseDataReceived((SerialPortData)((int)e.EventType));
        }



        /// <summary>
        /// 原始串口对象
        /// </summary>
        public override object OriginSerialPort
        {
            get { return _serialPort; }
        }

        /// <summary>
        /// 指示串口对象打开或关闭状态
        /// </summary>
        public override bool IsOpen
        {
            get
            {
                return this._serialPort.IsOpen;
            }
        }

        /// <summary>
        /// 获取接收缓冲区中数据字节数
        /// </summary>
        public override int BytesToRead
        {
            get
            {
                return this._serialPort.BytesToRead;
            }
        }

        /// <summary>
        /// 从输入缓冲区读取一些字节,并将读取到的字节写入字节数组指定的偏移量处
        /// </summary>
        /// <param name="buffer">将输入写入到其中的字节数据</param>
        /// <param name="offset">要写入字节buffer中偏移量</param>
        /// <param name="count">最多读取的字节数,如果count大于输入缓冲区中的字节数,则读取较少的字节</param>
        /// <returns>读取的字节数</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            return this._serialPort.Read(buffer, offset, count);
        }


        /// <summary>
        /// 将指定的字符串写入串行端口
        /// 异常:
        /// T:System.InvalidOperationException:指定的端口未打开。
        /// T:System.ServiceProcess.TimeoutException:该操作未在超时时间到期之前完成。
        /// </summary>
        /// <param name="text">输出字符串</param>
        public override void Send(string text)
        {
            this._serialPort.Write(text);
        }

        /// <summary>
        /// 使用缓冲区的数据将指定数量的字节写入串行端口
        /// 异常:
        /// T:System.InvalidOperationException:指定的端口未打开。
        /// T:System.ArgumentOutOfRangeException:offset 或 count 参数超出了所传递的 buffer 的有效区域。offset 或 count 小于零。
        /// T:System.ArgumentException:offset 加上 count 大于 buffer 的长度。
        /// T:System.ServiceProcess.TimeoutException:该操作未在超时时间到期之前完成。
        /// </summary>
        /// <param name="buffer">包含要写入端口的数据的字节数组</param>
        /// <param name="offset">buffer 参数中从零开始的字节偏移量，从此处开始将字节复制到端口</param>
        /// <param name="size">要写入的字节数</param>
        public override void Send(byte[] buffer, int offset, int size)
        {
            if (buffer == null || buffer.Length == 0)
            {
                return;
            }

            this._serialPort.Write(buffer, offset, size);
        }

        /// <summary>
        /// 使用缓冲区的数据将指定数量的字符写入串行端口
        /// 异常:
        /// T:System.InvalidOperationException:指定的端口未打开。
        /// T:System.ArgumentOutOfRangeException: offset 或 count 参数超出了所传递的 buffer 的有效区域。offset 或 count 小于零。
        /// T:System.ArgumentException:offset 加上 count 大于 buffer 的长度。
        /// T:System.ServiceProcess.TimeoutException:该操作未在超时时间到期之前完成。
        /// </summary>
        /// <param name="buffer">包含要写入端口的数据的字符数组</param>
        /// <param name="offset">buffer 参数中从零开始的字节偏移量，从此处开始将字节复制到端口</param>
        /// <param name="size">要写入的字符数</param>
        public override void Send(char[] buffer, int offset, int size)
        {
            if (buffer == null || buffer.Length == 0)
            {
                return;
            }

            this._serialPort.Write(buffer, offset, size);
        }

        /// <summary>
        /// 将指定的字符串和 System.IO.Ports.SerialPort.NewLine 值写入输出缓冲区
        /// 异常:
        /// T:System.InvalidOperationException:指定的端口未打开。
        /// T:System.TimeoutException:System.IO.Ports.SerialPort.WriteLine(System.String) 方法未能写入流。
        /// </summary>
        /// <param name="text">写入输出缓冲区的字符串</param>
        public override void SendLine(string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return;
            }

            this._serialPort.WriteLine(text);
        }


        /// <summary>
        /// 打开一个新的串行端口连接
        /// </summary>
        public override void Open()
        {
            this._serialPort.Open();
        }

        /// <summary>
        /// 关闭串口连接,将IsOpen设置为false,并释放内部资源
        /// </summary>
        public override void Close()
        {
            this._serialPort.Close();
        }

        /// <summary>
        /// 
        /// </summary>
        public override void Dispose()
        {
            this._serialPort.Dispose();
        }

    }
}
